package com.yzs.exam.entity.exam;

import com.yzs.exam.entity.Question;
import com.yzs.exam.utils.ExamUtil;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 智能试卷实体
 * @author yzs
 * @create 2021-04-28 16:50
 */
@Data
@NoArgsConstructor
public class ExamPaperAlgotithmBean {

    private Integer id;
    //适应度
    private double adaptationDegree = 0.00;

    //知识点覆盖率
    private double chapterCoverage = 0.00;

    //试卷总分
    private double totalScore = 0.00;

    //试卷难度系数
    private double difficulty = 0.00;


    private List<Question> questions = new ArrayList<>();

    /**
     * @param size 题目总数
     */
    public ExamPaperAlgotithmBean(int size) {
        for (int i = 0; i < size; i++) {
            questions.add(null);
        }
    }


    /**
     *  计算个体适应度 公式为：f = 1 - (1 - M/N) * f1 - |EP - P| * f2
     *  M/N:知识点覆盖率,EP为期望难度系数，P为种群个体难度系数
     *  f1=0时退化为只限制试题难度系数，f2=0时退化为只限制知识点分布
     * @param rule 组卷规则（表单对象传过来）
     * @param f1 知识点分布权重
     * @param f2 难度系数的权重
     */
    public void setAdaptationDegree(Rule rule, double f1, double f2) {
        if (adaptationDegree == 0){
            adaptationDegree = 1 - (1 -getChapterCoverage()) * f1 - Math.abs(rule.getDifficulty() -getDifficulty()) * f2;
        }
    }

    /**
     * 设置知识点覆盖率： 公式： 个体包含的知识点/期望包含的知识点
     * @param rule
     */
    public void setChapterCoverage(Rule rule) {
        if (chapterCoverage == 0){
            HashSet<Integer> expectRes = new HashSet<>();
            expectRes.addAll(rule.getChapters());//期望包含的知识点数
            Set<Integer>  actualRes = questions.stream().distinct().map(q -> q.getChapterId()).collect(Collectors.toSet());
            expectRes.retainAll(actualRes);//取交集
            chapterCoverage = (double) expectRes.size() / (double) rule.getChapters().size();
        }
    }

    /**
     * 计算试卷总分
     * @return
     */
    public double getTotalScore(){
        if (totalScore == 0){
            int total = 0;
            for (Question q: questions){
                total += q.getScore();
            }
            totalScore = Double.parseDouble(ExamUtil.scoreToVM(total));
        }
        return  totalScore;
    }


    /**
     * 计算试卷个体难度系数。计算公式：每题难度*分数/分数总和
     * @return
     */
    public double getDifficulty() {
        if(difficulty == 0){
            double _difficulty = 0;
            for (Question q: questions){
                _difficulty += Double.parseDouble(ExamUtil.scoreToVM(q.getScore())) * q.getDifficult();
            }
            difficulty = _difficulty / getTotalScore() / 5;
        }
        return difficulty;
    }

    /**
     * 添加题目
     * @param question
     */
    public void addQuestion(Question question){
        this.questions.add(question);
    }

    /**
     * 添加题目
     * @param index
     * @return
     */
    public void saveQuestion(Integer index, Question question){
        this.questions.set(index,question);
    }

    public Integer getQuestionSize(){
        return this.questions.size();
    }

    public boolean containsQuestion(Question question) {
        if (question == null) {
            for (int i = 0; i < questions.size(); i++) {
                if (questions.get(i) == null) {
                    return true;
                }
            }
        } else {
            for (Question q : questions) {
                if (q != null) {
                    if (q.equals(question)) {
                        return true;
                    }
                }
            }
        }
        return false;
    }


}
